package flca.mda.api.util;

import java.lang.reflect.Field;
import java.util.Properties;

import webapp.Tid;

public class FlexUtils {

	private final String BASE_TAB = "\t\t\t\t";
//	private final String TAB = "\t";
//	private final String NEWLINE = "\n";
	private final String Q = "\"";	
//	private final String VLD_PREFIX = "vld";
	
	private StringBuffer sValidatorsTags;
	private StringBuffer sValidators;
	private StringBuffer sUpdateViewScripts;
	private StringBuffer sUpdateModelScripts;
	
	private static NameUtils nu = new NameUtils();
	private static TypeUtils tu = new FlexTypeUtils();
	private static TemplateUtils tplu = new TemplateUtils();
	private static ValidatorUtils vu = new ValidatorUtils();
	private static SnippetUtils su = new SnippetUtils();

	/**
	 * This method must be called at the beginning of the jet
	 */
	public FlexUtils() 
	{
		sValidators = new StringBuffer();
		sValidatorsTags = new StringBuffer();
		sUpdateViewScripts = new StringBuffer();
		sUpdateModelScripts = new StringBuffer();
	}
	

	public String getDefaultValue(Field aField) 
	{
		String result = null;
		if (tu.isPrimitive(aField) || tu.isSimpleField(aField)) {
			result = nu.getIniFileValue("flex.default-value", tu.getTypeName(aField));
		} else {
			result = "null";
		}
		
		if (result == null) {
			result = "null";
		}
		return result;
	}
	
	public String getLabel(Field aField) 
	{
		return aField.getName(); //TODO Label annotation
	}

	/**
	 * This returns the validators example: 
	 *  <mx:StringValidator id="vldName" source="{idName}" property="text" required="true" enabled="false"/>
	 * @return
	 */
	public String getValidators() {
		return sValidators.toString();
	}

	public String getValidatorTags() {
		return sValidatorsTags.toString();
	}
	
	public String updateViewScripts() {
		return sUpdateViewScripts.toString();
	}

	public String updateModelScripts() {
		return sUpdateModelScripts.toString();
	}

	private String DONT_SHOW_PROPS[] = new String[] {
		"id", "parent", "createdAt", "createdBy", "modifiedAt", 
		"modifiedBy", "version", "locked", "lockedBy", "lockedAt",
	};

	/**
	 * Not all properties should be visible on the forms
	 * @param property
	 * @return
	 */
	public boolean dontShow(Field aField) {
		for (String s : DONT_SHOW_PROPS) {
			if (s.equals(aField.getName())) {
				return true;
			}
		}
		return false;
	}
	
	public String getExtendsAndImplements() 
	{
		return ""; //TODO
	}
	
	public String getExtendsAndImplementsLitteral(Class<?> uml2Class) 
	{
		return ""; //TODO
	}
	
	
	/**

	 * @param aField
	 * @return
	 */
	public Properties getSubsWithsForClass(Field aField)
	{
		//this will take care of the import
		tu.getTypeName(aField);
		
		Properties result = new Properties();
		result.put("uncapName", nu.uncapName(aField));
		result.put("capName", nu.capName(aField));
		result.put("type", tu.getTypeName(aField));
		result.put("defValue", getDefaultValue(aField));
		return result;
	}
	
	/**
	 * @param aField
	 * @return
	 */
	public Properties getSubsWithsForMxml(Field aField)
	{
		Properties result = new Properties();
		result.put("uncapName", nu.uncapName(aField));
		result.put("capName", nu.capName(aField));
		result.put("inputTag", getInputTag(aField));
		result.put("label", getLabel(aField));
		result.put("style", getStylename(aField));
		result.put("maxchars", getMaxChars(aField));
		result.put("restrict", getRestrict(aField));
		return result;
	}

	/**
	 * @param aField
	 * @return
	 */
	public Properties getSubsWithsForFlexCrudOper(CrudMethod aCrudMethod)
	{
		Class<?> crudent = aCrudMethod.getEntity(); 
		String entityName = tplu.getClassName(crudent, Tid.ENTITY.name()); 
		String pktype = tu.getIdTypeName(crudent);
		
		Properties result = new Properties();
		result.put("entity", entityName);
		result.put("pkType", pktype);
		return result;
	}

	public void fillValidatorTags(Field aField)
	{
		if (vu.mustValidate(aField)) {
			String kind = tu.getFieldSimpleKind(aField).name().toLowerCase();
			
			Properties props = new Properties();
			props.put("capName", nu.capName(aField));
			props.put("max", ""); //TODO
			props.put("min", ""); //TODO
			
			String req = "required=" + Q;
			req += (vu.isRequired(aField)) ? "true" + Q : "false" + Q;
			props.put("required", req);
			
			sValidatorsTags.append("\t" + su.getSnippet("flex.validator.tag" , kind, props) + "\n");
			sValidators.append(BASE_TAB + "vld" + nu.capName(aField) + ",\n");
		}
	}
	
	/**
	 * note Enum, One2Manu and Many2One are filtered out before this step
	 * @param aField
	 * @return
	 */
	public String getInputTag(Field aField)
	{
		String result = "mx:TextInput" ;
		if (tu.isDate(aField.getType())) {
			result = "cs:DateInput";
		} else if (tu.isTime(aField.getType())) {
			result = "cs:DateInput";
		} else if (tu.isBoolean(aField.getType())) {
			result = "mx:CheckBox";
		}
		return result;
	}

	public String getStylename(Field aField)
	{
		if (vu.mustValidate(aField)) {
			if (vu.isRequired(aField)) {
				return "tiNormalRequired";
			}
		}
		
		return "tiNormal";
	}

	public String getMaxChars(Field aField)
	{
		return "";
	}

	public String getRestrict(Field aField)
	{
		String result = "";
		if (tu.isNumeric(aField)) {
			result = "restrict='0-9 .'";
		} if (tu.isDate(aField.getType())) {
			result = "restrict='0-9 :'";
		}
		return result;
	}
	
	public boolean isJoinTable() 
	{
		return false;
	}
	
	public JoinTableProps[] getJoinTableProps()
	{
		return new JoinTableProps[] {new JoinTableProps(), new JoinTableProps()} ;
	}
	

}